import base64
import json
import random
import datetime
import re
import os
import mimetypes
from AI import image_animation
from wsgiref.util import FileWrapper
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect, StreamingHttpResponse
from django.shortcuts import render, redirect
from rest_framework.views import APIView
from .models import user_login, user_image_his
from rest_framework import serializers  # 序列化
from rest_framework.response import Response
from login.models import email_code
from django.conf import settings
from django.core.mail import send_mail

"""
接口规范：
/book/      GET         查看所有资源，返回所有资源
/book/      POST        添加资源，返回添加资源
/book/      GET         查看某个资源，返回这个资源
/book/      PUT         编辑某个资源，返回编辑之后的资源
/book/      DELETE      删除某个资源，返回空
"""


def ws_demo(request):
    if request.method == 'GET':
        return render(request, "wx_img.html")


# Create your views here.
# 针对模型设计序列化器  如果不做这个django原生是无法发送json数据到客户端， 既前后端分离开发所必须的
class Userserializers(serializers.Serializer):
    # 字段名必须和models的一样如果不一样需要像第二个字段哪那样处理
    # 如果这里不写某个字段那么序列化器也不会有这个字段
    userid = serializers.CharField(max_length=11, source="username")
    passwd = serializers.CharField(max_length=15, source="user_passwd")
    email = serializers.EmailField(required=False)

    def create(self, validated_data):  # 这个方法重写父类（必须）
        return user_login.objects.create(**self.validated_data)


# 如果不想自己实现 create update 就用这个 类似于 form和modelform
# class Userserializers(serializers.ModelSerializer):
#     class Meta:
#         model = user_login
# 必须基于CBV
from rest_framework_jwt.settings import api_settings

# 生成荷载
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
# 生成token
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

from .jwt_custom import JwtAuthentication


class User_login(APIView):
    # 局部禁用jwt认证
    authentication_classes = []
    """
    APIView 是基于django的view为基础进行开发
    """

    def get(self, request):

        return render(request, 'login.html')

    def post(self, request):
        Serializerdata = Userserializers(data=request.data)
        # 判断数据是否合法
        if Serializerdata.is_valid():
            user = user_login.objects.filter(username=Serializerdata.data['userid'],
                                             user_passwd=Serializerdata.data['passwd']).first()
            if user:
                print("登录成功")
                # 登录成功，签发token,通过当前登录用户获取荷载（payload）
                payload = jwt_payload_handler(user)
                # 通过payload生成token串（三段：头，payload，签名）
                token = jwt_encode_handler(payload)
                response = {'code': 100, 'msg': '登录成功', 'token': token}
                return Response(response)
            else:
                return JsonResponse({"code": 700, "error": "账号或者密码错误"})
        return Response(Serializerdata.errors)


# 用来给小程序用户获取token
class xcx_register_token(APIView):
    authentication_classes = []

    def post(self, request):
        print(request.data)
        if len(request.data['userid']) != 16 and request.data['passwd'][-1] != "^":
            render(request, 'login.html')
        user = user_login.objects.filter(username=request.data['userid'])
        if user:
            user = user_login.objects.filter(username=request.data['userid'],
                                             user_passwd=request.data['passwd'][:16]).first()
            if user:
                payload = jwt_payload_handler(user)
                # 通过payload生成token串（三段：头，payload，签名）
                token = jwt_encode_handler(payload)
                return Response({"code": "207", "token": token})

        else:
            user_login.objects.create(username=request.data['userid'],
                                      user_passwd=request.data['passwd'][:16])
            user = user_login.objects.filter(username=request.data['userid'])
            payload = jwt_payload_handler(user)
            # 通过payload生成token串（三段：头，payload，签名）
            token = jwt_encode_handler(payload)
            return Response({"code": "207", "token": token})


class User_register(APIView):
    # 局部禁用jwt认证
    authentication_classes = []
    """
    APIView 是基于django的view为基础进行开发
    """

    def get(self, request):
        return render(request, 'registe.html')

    def post(self, request):
        # password = hashlib.md5(password.encode(encoding="UTF-8")).hexdigest(),

        # 因为注册部分使用了两个model，所以使用两个序列化器,两者只会保存符合自己数据的部分
        SerializerUser = Userserializers(data=request.data)
        SerializerEmail = CodeSerializers(data=request.data)
        # 判断数据是否合法
        if SerializerUser.is_valid() and SerializerEmail.is_valid():
            code = email_code.objects.filter(email=SerializerEmail.data['email'], code=SerializerEmail.data['code'])
            if not code:
                return JsonResponse({"code": "验证码错误"})
            else:
                # 检查该邮箱是否注册过
                use = user_login.objects.filter(email=SerializerEmail.data['email'])
                if use:
                    return JsonResponse({"email": "该邮箱已经注册"})

                SerializerUser.save()

                return JsonResponse({"code": 207, "success": "注册成功", "userid": SerializerUser.data["userid"]})
        # 返回所以的错误信息
        response = {}
        for i in SerializerUser.errors:
            response[i] = str(SerializerUser.errors[i][0])
        SerializerEmail.is_valid()
        for i in SerializerEmail.errors:
            response[i] = str(SerializerEmail.errors[i][0])

        print(response)
        return JsonResponse(response)


# 定义序列化器
class CodeSerializers(serializers.Serializer):
    email = serializers.EmailField()
    code = serializers.CharField(max_length=5, required=False)

    def create(self, validated_data):
        return email_code.objects.create(**self.validated_data)


# 获取验证码
class get_code(APIView):
    authentication_classes = []

    def get(self, request):
        return render(request, 'login.html')

    def post(self, request):
        print("________", request.data)
        code_serializer = CodeSerializers(data=request.data)
        # 判断数据是否合法
        if code_serializer.is_valid():
            email_ = email_code.objects.filter(email=request.data['email'])
            # 获取随机验证码

            code = random.randint(10000, 99999)
            # 如果存在值，则更新这条记录
            if email_:
                email_.update(code=f'{code}', code_time=datetime.datetime.now())

            else:
                # 存入数据库中
                email_code.objects.create(email=request.data['email'], code=f'{code}')
            # 发送验证码
            send_mail(
                subject='活图网注册验证码',
                message='{0}为你的验证码，打死也不要告诉别人，验证码有效期60s'.format(code),
                from_email=settings.EMAIL_HOST_USER,
                recipient_list=[request.data['email']])
            return JsonResponse({'code': 200, 'getcode': 1, 'time': datetime.datetime.now()})
        return Response(code_serializer.errors)


def text(request):
    if request.method == "POST":
        print(request.COOKIES)
        # a = email_code.objects.filter(email="1adw@qq.com")
        # b = email_code.objects.filter(email="13321324@qq.com")
        # print(a[0].code_time)
        # print(type(b[0].code_time - a[0].code_time))
        random.randint(10000, 99999)

        return render(request, "login.html")
    else:
        return JsonResponse({"code": 200, "getcode": "true", "time": datetime.datetime.now()})


# 上传文件
class upload(APIView):

    def get(self, request):
        return render(request, "upimg.html")

    def post(self, request):
        print(request.data)
        # datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        file_name = str(datetime.datetime.now().strftime("%Y_%m_%d_%H-%M-%S")+'_'+request.data.get("name"))
        print(file_name)
        with open(r"AI\Inputs\{0}.jpg".format(file_name), "wb") as f2:
            data = str(request.POST.get("base64"))
            f2.write(base64.b64decode(data.replace(" ", "+")))
            print("保存完成")
        user_image_his.objects.create(img_file_time=datetime.datetime.now().strftime("%Y_%m_%d_%H-%M-%S"),
                                      user_name=request.data.get("name"))
        image_animation.run(output_path=r"AI\output\{0}.mp4".format(file_name),
                            source_path=r"AI\Inputs\{0}.jpg".format(file_name))
        # main()
        return JsonResponse({"code": "207", "success": "ok", "file_name": file_name})


def my_redirect(request):
    if request.method == "GET":
        page = request.GET.get('page')
        ret_page = {
            "upimg": render(request, "upimg.html")
        }
        return ret_page[page]


# ---------------------------------------------------------------------
#  播放视频

def file_iterator(file_name, chunk_size=8192, offset=0, length=None):
    # 每次最多读取8kb
    with open(file_name, "rb") as f:
        f.seek(offset, os.SEEK_SET)
        remaining = length  # 还有多少未读取
        while True:
            bytes_length = chunk_size if remaining is None else min(remaining, chunk_size)
            data = f.read(bytes_length)
            if not data:  # 没有数据了 退出
                break
            if remaining:
                remaining -= len(data)
            yield data


def stream_video(request, arg_path):
    """将视频文件以流媒体的方式响应"""
    range_header = request.META.get('HTTP_RANGE', '').strip()
    range_re = re.compile(r'bytes\s*=\s*(\d+)\s*-\s*(\d*)', re.I)
    range_match = range_re.match(range_header)
    # 这里规定存放视频文件夹
    path = r"AI\\output\\" + arg_path
    print(path)
    size = os.path.getsize(path)
    content_type, encoding = mimetypes.guess_type(path)
    content_type = content_type or 'application/octet-stream'
    if range_match:
        # first_byte播放到的位置
        # 下次播放的位置
        # range_match.groups('START'), range_match.groups("END")
        first_byte, last_byte = range_match.groups()
        first_byte = int(first_byte) if first_byte else 0
        # 从播放的位置往后读取10M的数据
        last_byte = first_byte + 1024 * 1024 * 10
        if last_byte >= size:  # 如果想读取的位置大于文件大小
            last_byte = size - 1  # 最后将图片全部读完
        length = last_byte - first_byte + 1  # 此次读取的长度（字节）
        resp = StreamingHttpResponse(file_iterator(path, offset=first_byte, length=length), status=206,
                                     content_type=content_type)
        resp['Content-Length'] = str(length)
        resp['Content-Range'] = 'bytes %s-%s/%s' % (first_byte, last_byte, size)
    else:
        resp = StreamingHttpResponse(FileWrapper(open(path, 'rb')), content_type=content_type)
        resp['Content-Length'] = str(size)
    resp['Accept-Ranges'] = 'bytes'
    return resp


class query_user_his(APIView):
    def get(self, request):
        return Response("text")

    def post(self, request):
        from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
        print(request.POST.get("user"), "d  ")
        res = user_image_his.objects.filter(user_name=request.POST.get("user"))
        paginator = Paginator(res, 10)
        # res = user_image_his.objects.filter(user_name="962527148").values()[0]["user_name"]
        # <QuerySet [{'id': 1, 'img_file_time': '2023-06-03-23:16:46', 'user_name': '962527148'}]>
        page = request.GET.get('page')
        try:
            data = paginator.page(page)
        except PageNotAnInteger:
            data = paginator.page(1)  # 如果不为整数默认第一页
        except EmptyPage:
            data = paginator.page(paginator.num_pages)  # 如果页数超出范围，则默认为最后一页
        result = []
        for item in data:
            result.append({
                'time': item.img_file_time,
                'id': item.id
            })
        return JsonResponse({'data': result})
